package com.gzsxy.esjy.service.statistical.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.gzsxy.esjy.feign.Auth.AuthFeignService;
import com.gzsxy.esjy.feign.Order.OrderFeignService;
import com.gzsxy.esjy.redis.extend.RedisService;
import com.gzsxy.esjy.redis.user.ISystemUser;
import com.gzsxy.esjy.service.base.DictionaryConstants;
import com.gzsxy.esjy.service.base.dto.response.DefaultResponse;
import com.gzsxy.esjy.service.base.dto.response.OrderCountRsp;
import com.gzsxy.esjy.service.base.dto.response.StatisicalRsp;
import com.gzsxy.esjy.service.statistical.entity.Statisical;
import com.gzsxy.esjy.service.statistical.dao.StatisicalMapper;
import com.gzsxy.esjy.service.statistical.service.StatisicalService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.toList;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author zxl
 * @since 2022-03-16
 */
@Service
@Slf4j
public class StatisicalServiceImpl extends ServiceImpl<StatisicalMapper, Statisical> implements StatisicalService {

    private static final SimpleDateFormat DATE_FORMAT =  new SimpleDateFormat( "yyyy-MM-dd ");

    @Autowired
    private RedisService redisService;

    @Autowired
    private ISystemUser iSystemUser;

    @Autowired
    private AuthFeignService authFeignService;

    @Autowired
    private OrderFeignService orderFeignService;

    /**
     * @description: 生成统计记录
     * @param day 日期
     * @return
     */
    @Override
    public StatisicalRsp getAllStatisicalByDay(String day) {
        if(org.apache.commons.lang3.StringUtils.isBlank(day)){
            day = DATE_FORMAT.format(new Date());
        }
        //判断当前用户是否为系统管理员（默认查询管理员所拥有的）
        Boolean isAdmin = (Boolean) iSystemUser.get("isAdmin", true);
        if (!isAdmin){
            String userId = (String) iSystemUser.get("id", "");
            if (StringUtils.isNotEmpty(userId)){
                StatisicalRsp statisicalRsp = getselectone(userId, day);
                return statisicalRsp;
            }
        }
        //查询管理员所拥有的可以查看当前系统登录注册用户数
        StatisicalRsp statisicalRsp = getselectone(DictionaryConstants.ADMIN, day);
        return statisicalRsp;
    }


    private StatisicalRsp getselectone(String userId,String day){
        //TODO admin为所有商家的销售额
        //查询今日销售额()
        LambdaQueryWrapper wrapper = selectCondition(userId, day);
        Statisical statisical = baseMapper.selectOne(wrapper);
        //TODO 如果统计库里没有数据，则要远程查询相关记录
//        if (ObjectUtils.isEmpty(statisical)){
//
//        }
        StatisicalRsp statisicalRsp = new StatisicalRsp();
        BeanUtils.copyProperties(statisical,statisicalRsp);
        LambdaQueryWrapper wrapper1 = selectCondition(userId, getYesterday());
        //获取昨天的销售额
        Statisical statisical1 = baseMapper.selectOne(wrapper1);
        statisicalRsp.setYesterdaySalesNum(statisical1.getSalesNum());
        //查询最近7天的总销量
        Integer  sevendaySalesNum =  baseMapper.selectSevendaySalesNum(userId);
        statisicalRsp.setSevendaySalesNum(sevendaySalesNum);
        return statisicalRsp;
    }


    /**
     * @description: 查询对象
     * @param
     * @return
     */
    private LambdaQueryWrapper selectCondition(String userId,String day){
        LambdaQueryWrapper<Statisical> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(Statisical::getDateCalculated,day);
        wrapper.eq(Statisical::getUserId,userId);
        return wrapper;
    }
    /**
     * @description: 修改每日订单数量
     * @param
     * @return
     */
    @Override
    public void getOrderStatistical(String userId) {
        String format = DATE_FORMAT.format(new Date());


    }


    /**
     * @description: 定时任务凌晨12.00统计昨天网站的登录注册数据和订单数据
     * @param
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void LoginStatistics() {
        //统计不同商家当日的订单量与销量
        try {
            String day = getYesterday();
            DefaultResponse response = orderFeignService.getOrderStatistical(day);
            List<OrderCountRsp> list = JSON.parseArray(JSON.toJSONString(response.getData()), OrderCountRsp.class);
            log.info("时间【{}】系统各商家的订单数据【{}】",day,JSON.toJSONString(list));
            if (CollectionUtils.isNotEmpty(list)){
                List<Statisical> statisicals = JSON.parseArray(JSON.toJSONString(list), Statisical.class);
                statisicals.stream().map(p -> {
                    p.setDateCalculated(day);
                    LambdaQueryWrapper wrapper = selectCondition(p.getUserId(), day);
                    baseMapper.update(p,wrapper);
                    return p;
                }).collect(Collectors.toList());

                //TODO 管理员当日统计的是系统订单总数和系统销量总数
                //当天系统总订单数
                long orderNum = statisicals.stream().collect(Collectors.summarizingInt(Statisical::getOrderNum)).getSum();
                //当天系统总交易额
                Double salesNum = statisicals.stream().collect(Collectors.summingDouble(Statisical::getSalesNum));
                //获取昨天一整天的登录人数
                Integer LoginNum = (Integer) redisService.getValue(DictionaryConstants.LOGIN_NUM);
                //获取昨天一整天的注册人数
                DefaultResponse defaultResponse = authFeignService.selectRegisterNumByDay(day);
                Integer registerNum = (Integer) defaultResponse.getData();
                Statisical statisical = new Statisical();
                statisical.setLoginNum(LoginNum);
                statisical.setRegisterNum(registerNum);
                statisical.setDateCalculated(day);
                statisical.setUserId(DictionaryConstants.ADMIN);
                statisical.setOrderNum((int) orderNum);
                statisical.setSalesNum(salesNum);
                LambdaQueryWrapper wrapper = selectCondition(statisical.getUserId(), day);
                log.info("时间【{}】系统今日订单销量【{}】",day,JSON.toJSONString(statisical));
                baseMapper.update(statisical,wrapper);
            }
        } finally {
            //清除昨天登录次数
            redisService.remove(DictionaryConstants.LOGIN_NUM);
        }

    }






    /**
     * @description: 初始化每日商家的订单销量数据
     * @param
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void InitStatisicals(String date){
        //获取当前系统的所有商家
        List<String> userIdList = (List<String>) redisService.getValue(DictionaryConstants.USER_ID);
        //添加管理员
        userIdList.add(DictionaryConstants.ADMIN);
        List<Statisical> list = userIdList.stream().map(id -> {
            Statisical statisical = new Statisical();
            statisical.setUserId(id);
            statisical.setDateCalculated(date);
            statisical.setOrderNum(DictionaryConstants.NUMBER_0);
            statisical.setSalesNum(DictionaryConstants.NUMBER_0_0);
            statisical.setRegisterNum(DictionaryConstants.NUMBER_0);
            statisical.setLoginNum(DictionaryConstants.NUMBER_0);
            return statisical;
        }).collect(toList());
        this.saveBatch(list);
        log.info("初始化商家成功！当前时间【{}】",DATE_FORMAT.format(new Date()));
    }


    /**
     * @description: 更新记录
     * @param
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateStatisicals(String userId, Double salesNum) {
        LambdaQueryWrapper wrapper = selectCondition(userId, DATE_FORMAT.format(new Date()));
        Statisical statisical = baseMapper.selectOne(wrapper);
        LambdaQueryWrapper wrapper1 = selectCondition(DictionaryConstants.ADMIN, DATE_FORMAT.format(new Date()));
        Statisical statisical1 = baseMapper.selectOne(wrapper1);
        statisical1.setOrderNum(statisical1.getOrderNum()+1);
        statisical1.setSalesNum(statisical1.getSalesNum()+salesNum);
        baseMapper.updateById(statisical1);
        if (ObjectUtils.isNotEmpty(statisical)){
                statisical.setOrderNum(statisical.getOrderNum()+1);
                statisical.setSalesNum( (statisical.getSalesNum()+salesNum));
                baseMapper.updateById(statisical);
        } else {
            log.error("当前商家id【{}】与时间【{}】无相关记录！！",userId,DATE_FORMAT.format(new Date()));
        }
    }

    /**
     * @description: 获取昨天时间
     * @param
     * @return
     */
    public String  getYesterday(){
        Calendar cal=Calendar.getInstance();
        cal.add(Calendar.DATE,   -1);
        String day = DATE_FORMAT.format(cal.getTime());
        return day;
    }



    public static void main(String[] args) {
        Calendar cal=Calendar.getInstance();
        cal.add(Calendar.DATE,   -1);
        System.out.println(DATE_FORMAT.format(cal.getTime()));
    }

    /**
     * @description: 显示统计数据
     * @param begin 开始时间
     * @param end 结束时间
     * @return
     */
    @Override
    public Map<String, Map<String, Object>> getChartData(String begin, String end) {
        //判断当前用户是否为系统管理员（默认查询管理员所拥有的）
        String userId = DictionaryConstants.ADMIN;
        Boolean isAdmin = (Boolean) iSystemUser.get("isAdmin", true);
        if (!isAdmin){
            userId = (String) iSystemUser.get("id", "admin");
        }
        //系统注册数统计
        Map<String, Object> registerNum = this.getChartDataByType(begin, end, "register_num",userId);
        //学员登录数统计
        Map<String, Object> loginNum = this.getChartDataByType(begin, end, "login_num",userId);
        //订单数统计
        Map<String, Object> orderNum = this.getChartDataByType(begin, end, "order_num",userId);
        //订单总额统计
        Map<String, Object> salesNum = this.getChartDataByType(begin, end, "sales_num",userId);

        Map<String, Map<String, Object>> map = new HashMap<>();
        map.put("registerNum", registerNum);
        map.put("loginNum", loginNum);
        map.put("orderNum", orderNum);
        map.put("salesNum", salesNum);
        return map;
    }



    /**
     * 根据时间和要查询的列查询数据
     * @param begin
     * @param end
     * @param type 要查询的列名
     * @return
     */
    private Map<String, Object> getChartDataByType(String begin, String end, String type,String userId){
        Map<String, Object> map = new HashMap<>();
        List<String> xList = new ArrayList<>(); //日期列表
        List<Object> yList = new ArrayList<>(); //数据列表

        QueryWrapper<Statisical> wrapper = new QueryWrapper<>();
        wrapper.select("date_calculated", type);
        wrapper.between("date_calculated", begin, end);
        wrapper.eq("user_id",userId);

        List<Map<String, Object>> mapsData = baseMapper.selectMaps(wrapper);
        for (Map<String, Object> data : mapsData) {
            String dateCalculated = (String)data.get("date_calculated");
            xList.add(dateCalculated);
            yList.add(data.get(type));
        }

        map.put("xData", xList);
        map.put("yData", yList);
        return map;
    }
}
